package org.carpediem.conman.dao;

import org.carpediem.conman.entity.Contact;
import org.carpediem.conman.entity.Document;
import org.carpediem.conman.Util;
import org.carpediem.schema.conman.BContactInfo;
import org.carpediem.schema.conman.ContactInfo;
import org.carpediem.schema.conman.DocumentInfo;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import java.sql.SQLException;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author Mark Petrovic
 */
public class ContactDaoImpl extends ContactDao {
    private final Logger logger = Logger.getLogger(ContactDaoImpl.class.getName());

   /* private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        hibernateTemplate = new HibernateTemplate(sessionFactory);
    }*/

    public Contact add(ContactInfo cInfo, byte[] docBuffer) {
        Contact contact = buildContact(cInfo, docBuffer);
        hibernateTemplate.saveOrUpdate(contact);

        getS3Persister().enqueue(contact);
        cacheLocally(contact);
        index(contact);

        return contact;
    }

    public Contact get(long contactId) {
        return (Contact) hibernateTemplate.get(Contact.class, contactId);
    }

    public Contact getByEmail(final String emailAddress) {
        return (Contact) hibernateTemplate.execute(new ByEmail(emailAddress));
    }

    public List<Contact> getAllContacts() {
        return hibernateTemplate.loadAll(Contact.class);
    }

    public Contact update(Contact contact) {
        hibernateTemplate.saveOrUpdate(contact);
        return contact;
    }

    private Contact buildContact(ContactInfo cInfo, byte[] docBuffer) {
        BContactInfo bInfo = cInfo.getContact();

        Contact contact = new Contact();
        contact.setEmailAddress(bInfo.getEmailAddress().trim().toLowerCase());
        contact.setFirstName(bInfo.getFirstName());
        contact.setLastName(bInfo.getLastName());
        contact.setAddress1(bInfo.getAddress1());
        contact.setAddress2(bInfo.getAddress2());
        contact.setCity(bInfo.getCity());
        contact.setState(bInfo.getState());

        List<DocumentInfo> docInfos = bInfo.getDocumentInfo();
        if (docInfos.size() > 0) {
            for (DocumentInfo dInfo : docInfos) {
                Document document = new Document();
                document.setMimeType(dInfo.getMimetype());
                document.setUri(getS3Persister().documentUri(docBuffer));
                document.setOriginalName(dInfo.getOriginalName());
                document.setHexMD5(Util.hexDigest(docBuffer));
                document.setBuffer(docBuffer);
                contact.addDocument(document);
            }
        }
        return contact;
    }

    private class ByEmail implements HibernateCallback {
        private String emailAddress;

        public ByEmail(String emailAddress) {
            this.emailAddress = emailAddress.trim().toLowerCase();
        }

        public Object doInHibernate(Session session) throws HibernateException, SQLException {
            Query query = session.createQuery("from Contact where emailAddress =:anEmail");
            query.setParameter("anEmail", emailAddress);
            return query.uniqueResult();
        }
    }
}
